package com.kpmg.datalake.web.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.kpmg.datalake.common.constants.Constants;
import com.kpmg.datalake.common.dynamicdatasource.DBTypeEnum;
import com.kpmg.datalake.common.dynamicdatasource.DataSourceLocalStoreServiceImpl;
import com.kpmg.datalake.common.dynamicdatasource.DataSourceStoreService;
import com.kpmg.datalake.common.dynamicdatasource.DynamicDataSource;
import com.kpmg.datalake.common.enums.UseOrDelEnum;
import com.kpmg.datalake.common.service.IDbPrmsnService;
import com.kpmg.datalake.common.utils.EncrypUtil;
import com.kpmg.datalake.common.utils.LogUtils;
import com.kpmg.datalake.common.utils.SpringUtil;
import com.kpmg.datalake.db.model.DbPrmsn;
import java.util.HashMap;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * Durid数据源配置
 *
 * @author Tony
 */
@Configuration
@EnableTransactionManagement
public class DataSourceConfig implements ApplicationListener<ContextRefreshedEvent> {

    @Value("${spring.datasource.druid.url}")
    private String url;
    @Value("${spring.datasource.druid.username}")
    private String username;
    @Value("${spring.datasource.druid.password}")
    private String password;
    @Value("${spring.datasource.druid.maxActive}")
    private int maxActive;
    @Value("${spring.datasource.druid.driverClassName}")
    private String driverClassName;
    @Value("${spring.datasource.druid.initialSize}")
    private int initialSize;
    @Value("${spring.datasource.druid.minIdle}")
    private int minIdle;
    @Value("${spring.datasource.druid.maxWait}")
    private int maxWait;
    @Value("${spring.datasource.druid.testOnBorrow}")
    private boolean testOnBorrow;
    @Value("${spring.datasource.druid.testOnReturn}")
    private boolean testOnReturn;
    @Value("${spring.datasource.druid.validationQuery}")
    private String validationQuery;
    @Value("${spring.datasource.druid.testWhileIdle}")
    private boolean testWhileIdle;
    @Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")
    private int timeBetweenEvictionRunsMillis;
    @Value("${spring.datasource.druid.minEvictableIdleTimeMillis}")
    private int minEvictableIdleTimeMillis;




    @Bean
    @Primary
    public DataSource druidDataSource() {
        DruidDataSource dataSource = getDataSourceConfiguration();
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setDefaultTargetDataSource(dataSource);
        dynamicDataSource.setTargetDataSources(new HashMap<>(16));
        return dynamicDataSource;
    }

    @Bean
    public DataSourceTransactionManager dataSourceTransactionManager(DataSource dataSource) {
        DataSourceTransactionManager manager = new DataSourceTransactionManager();
        manager.setDataSource(dataSource);
        return manager;
    }

    @Bean
    @Primary
    public DataSourceStoreService dataSourceStoreDevService() {
        return new DataSourceLocalStoreServiceImpl();

    }

    /**
     * 动态组装 数据池对象
     *
     * @return DruidDataSource
     */
    public DruidDataSource getDataSourceConfiguration() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        String tempUsername = EncrypUtil.decryptAes(username, Constants.ENCRY_KEY);
        dataSource.setUsername(tempUsername);
        String tempPassword = EncrypUtil.decryptAes(password, Constants.ENCRY_KEY);
        dataSource.setPassword(tempPassword);
        dataSource.setDriverClassName(driverClassName);
        dataSource.setInitialSize(initialSize);
        dataSource.setMinIdle(minIdle);
        dataSource.setMaxActive(maxActive);
        dataSource.setMaxWait(maxWait);
        dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        dataSource.setValidationQuery(validationQuery);
        dataSource.setTestWhileIdle(testWhileIdle);
        dataSource.setTestOnBorrow(testOnBorrow);
        dataSource.setTestOnReturn(testOnReturn);
        return dataSource;
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent cont) {
        if (cont.getApplicationContext().getParent() == null) {
          IDbPrmsnService dbPrmsnService = SpringUtil.getBean(IDbPrmsnService.class);
          DbPrmsn dbPrmsn = new DbPrmsn();
          dbPrmsn.setDelInd(UseOrDelEnum.USE.getIntCode());
          List<DbPrmsn> list = dbPrmsnService.selectList(new EntityWrapper<>(dbPrmsn));
            for (DbPrmsn dbprmsn : list) {
                String dataSourceId = dbprmsn.getPrjId();
                String dbType = dbprmsn.getDbTpnm();
                String ip = dbprmsn.getIpAdr();
                String dbName = dbprmsn.getDbInstnnm();
              Integer dbPort = dbprmsn.getPort();
                String dbUserName = dbprmsn.getDbAcc();
                String dbPassword = dbprmsn.getDbPwd();
                DruidDataSource targetDataSource = getDataSourceConfiguration();
                dbUserName = EncrypUtil.decryptAes(dbUserName, Constants.ENCRY_KEY);
                targetDataSource.setUsername(dbUserName);
                dbPassword = EncrypUtil.decryptAes(dbPassword, Constants.ENCRY_KEY);
                targetDataSource.setPassword(dbPassword);
                targetDataSource.setDriverClassName(DBTypeEnum.getDriverClass(dbType));
              targetDataSource.setUrl(DBTypeEnum.getUrl(dbType, ip, dbPort.toString(), dbName));
                try {
                    DataSourceStoreService dataSourceStoreService = SpringUtil.getBean(DataSourceStoreService.class);
                    dataSourceStoreService.checkAndRefreshDataSource(dataSourceId, targetDataSource);
                } catch (Exception e) {
                    LogUtils.error(e.getMessage());
                }
            }
        }

    }
}
